/*

 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <vector>
#include <string>
#include <gtest/gtest.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include "It_process_plimits.h"

using namespace std;
using namespace testing::ext;
namespace OHOS {
class ProcessPlimitsTest : public testing::Test {
public:
    static void SetUpTestCase(void) {}
    static void TearDownTestCase(void) {}

protected:
    virtual void SetUp();
    virtual void TearDown();

private:
    int RmPlimitsDir(const std::string &path, bool isRoot);
    inline bool IsFile(const std::string &file);
    inline bool IsDir(const std::string &path);
    inline bool IsSpecialDir(const std::string &path);
};

#if defined(LOSCFG_USER_TEST_SMOKE)
#if defined(LOSCFG_USER_TEST_PROCESS_LIMITS)
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits001, TestSize.Level0)
{
    ItProcessPlimits001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits003, TestSize.Level0)
{
    ItProcessPlimits003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits005, TestSize.Level0)
{
    ItProcessPlimits005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits006, TestSize.Level0)
{
    ItProcessPlimits006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits007, TestSize.Level0)
{
    ItProcessPlimits007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits009, TestSize.Level0)
{
    ItProcessPlimits009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits010, TestSize.Level0)
{
    ItProcessPlimits010();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits011, TestSize.Level0)
{
    ItProcessPlimits011();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits012, TestSize.Level0)
{
    ItProcessPlimits012();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits014, TestSize.Level0)
{
    ItProcessPlimits014();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits016, TestSize.Level0)
{
    ItProcessPlimits016();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits017, TestSize.Level0)
{
    ItProcessPlimits017();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits018, TestSize.Level0)
{
    ItProcessPlimits018();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits019, TestSize.Level0)
{
    ItProcessPlimits019();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits020, TestSize.Level0)
{
    ItProcessPlimits020();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits021, TestSize.Level0)
{
    ItProcessPlimits021();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits022, TestSize.Level0)
{
    ItProcessPlimits022();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits023, TestSize.Level0)
{
    ItProcessPlimits023();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits024, TestSize.Level0)
{
    ItProcessPlimits024();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits025, TestSize.Level0)
{
    ItProcessPlimits025();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits026, TestSize.Level0)
{
    ItProcessPlimits026();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits028, TestSize.Level0)
{
    ItProcessPlimits028();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits032, TestSize.Level0)
{
    ItProcessPlimits032();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits033, TestSize.Level0)
{
    ItProcessPlimits033();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits034, TestSize.Level0)
{
    ItProcessPlimits034();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits035, TestSize.Level0)
{
    ItProcessPlimits035();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits036, TestSize.Level0)
{
    ItProcessPlimits036();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits037, TestSize.Level0)
{
    ItProcessPlimits037();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits038, TestSize.Level0)
{
    ItProcessPlimits038();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits043, TestSize.Level0)
{
    ItProcessPlimits043();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits044, TestSize.Level0)
{
    ItProcessPlimits044();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits045, TestSize.Level0)
{
    ItProcessPlimits045();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits046, TestSize.Level0)
{
    ItProcessPlimits046();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits047, TestSize.Level0)
{
    ItProcessPlimits047();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits048, TestSize.Level0)
{
    ItProcessPlimits048();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits049, TestSize.Level0)
{
    ItProcessPlimits049();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits050, TestSize.Level0)
{
    ItProcessPlimits050();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits053, TestSize.Level0)
{
    ItProcessPlimits053();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits054, TestSize.Level0)
{
    ItProcessPlimits054();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits055, TestSize.Level0)
{
    ItProcessPlimits055();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimits056, TestSize.Level0)
{
    ItProcessPlimits056();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid001, TestSize.Level0)
{
    ItProcessPlimitsPid001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid002, TestSize.Level0)
{
    ItProcessPlimitsPid002();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid003, TestSize.Level0)
{
    ItProcessPlimitsPid003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid004, TestSize.Level0)
{
    ItProcessPlimitsPid004();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid005, TestSize.Level0)
{
    ItProcessPlimitsPid005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid006, TestSize.Level0)
{
    ItProcessPlimitsPid006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid007, TestSize.Level0)
{
    ItProcessPlimitsPid007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid008, TestSize.Level0)
{
    ItProcessPlimitsPid008();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsPid009, TestSize.Level0)
{
    ItProcessPlimitsPid009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched001, TestSize.Level0)
{
    ItProcessPlimitsSched001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched002, TestSize.Level0)
{
    ItProcessPlimitsSched002();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched003, TestSize.Level0)
{
    ItProcessPlimitsSched003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched004, TestSize.Level0)
{
    ItProcessPlimitsSched004();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched005, TestSize.Level0)
{
    ItProcessPlimitsSched005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched006, TestSize.Level0)
{
    ItProcessPlimitsSched006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched007, TestSize.Level0)
{
    ItProcessPlimitsSched007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched008, TestSize.Level0)
{
    ItProcessPlimitsSched008();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched009, TestSize.Level0)
{
    ItProcessPlimitsSched009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched010, TestSize.Level0)
{
    ItProcessPlimitsSched010();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched011, TestSize.Level0)
{
    ItProcessPlimitsSched011();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched012, TestSize.Level0)
{
    ItProcessPlimitsSched012();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched013, TestSize.Level0)
{
    ItProcessPlimitsSched013();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsSched014, TestSize.Level0)
{
    ItProcessPlimitsSched014();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory001, TestSize.Level0)
{
    ItProcessPlimitsMemory001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory002, TestSize.Level0)
{
    ItProcessPlimitsMemory002();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory003, TestSize.Level0)
{
    ItProcessPlimitsMemory003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory004, TestSize.Level0)
{
    ItProcessPlimitsMemory004();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory005, TestSize.Level0)
{
    ItProcessPlimitsMemory005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory006, TestSize.Level0)
{
    ItProcessPlimitsMemory006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory007, TestSize.Level0)
{
    ItProcessPlimitsMemory007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory008, TestSize.Level0)
{
    ItProcessPlimitsMemory008();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory009, TestSize.Level0)
{
    ItProcessPlimitsMemory009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory010, TestSize.Level0)
{
    ItProcessPlimitsMemory010();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory011, TestSize.Level0)
{
    ItProcessPlimitsMemory011();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory012, TestSize.Level0)
{
    ItProcessPlimitsMemory012();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory013, TestSize.Level0)
{
    ItProcessPlimitsMemory013();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory014, TestSize.Level0)
 {
     ItProcessPlimitsMemory014();
 }
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory015, TestSize.Level0)
{
    ItProcessPlimitsMemory015();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory016, TestSize.Level0)
{
    ItProcessPlimitsMemory016();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsMemory017, TestSize.Level0)
{
    ItProcessPlimitsMemory017();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc001, TestSize.Level0)
{
    ItProcessPlimitsIpc001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc002, TestSize.Level0)
{
    ItProcessPlimitsIpc002();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc003, TestSize.Level0)
{
    ItProcessPlimitsIpc003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc004, TestSize.Level0)
{
    ItProcessPlimitsIpc004();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc005, TestSize.Level0)
{
    ItProcessPlimitsIpc005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc006, TestSize.Level0)
{
    ItProcessPlimitsIpc006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc007, TestSize.Level0)
{
    ItProcessPlimitsIpc007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc008, TestSize.Level0)
{
    ItProcessPlimitsIpc008();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc009, TestSize.Level0)
{
    ItProcessPlimitsIpc009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc010, TestSize.Level0)
{
    ItProcessPlimitsIpc010();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc011, TestSize.Level0)
{
    ItProcessPlimitsIpc011();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc012, TestSize.Level0)
{
    ItProcessPlimitsIpc012();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc013, TestSize.Level0)
{
    ItProcessPlimitsIpc013();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc014, TestSize.Level0)
{
    ItProcessPlimitsIpc014();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc015, TestSize.Level0)
{
    ItProcessPlimitsIpc015();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsIpc016, TestSize.Level0)
{
    ItProcessPlimitsIpc016();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices001, TestSize.Level0)
{
    ItProcessPlimitsDevices001();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices002, TestSize.Level0)
{
    ItProcessPlimitsDevices002();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices003, TestSize.Level0)
{
    ItProcessPlimitsDevices003();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices004, TestSize.Level0)
{
    ItProcessPlimitsDevices004();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices005, TestSize.Level0)
{
    ItProcessPlimitsDevices005();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices006, TestSize.Level0)
{
    ItProcessPlimitsDevices006();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices007, TestSize.Level0)
{
    ItProcessPlimitsDevices007();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices008, TestSize.Level0)
{
    ItProcessPlimitsDevices008();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices009, TestSize.Level0)
{
    ItProcessPlimitsDevices009();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices010, TestSize.Level0)
{
    ItProcessPlimitsDevices010();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices011, TestSize.Level0)
{
    ItProcessPlimitsDevices011();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices012, TestSize.Level0)
{
    ItProcessPlimitsDevices012();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices013, TestSize.Level0)
{
    ItProcessPlimitsDevices013();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices014, TestSize.Level0)
{
    ItProcessPlimitsDevices014();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices015, TestSize.Level0)
{
    ItProcessPlimitsDevices015();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices016, TestSize.Level0)
{
    ItProcessPlimitsDevices016();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices017, TestSize.Level0)
{
    ItProcessPlimitsDevices017();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices018, TestSize.Level0)
{
    ItProcessPlimitsDevices018();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices019, TestSize.Level0)
{
    ItProcessPlimitsDevices019();
}
HWTEST_F(ProcessPlimitsTest, ItProcessPlimitsDevices020, TestSize.Level0)
{
    ItProcessPlimitsDevices020();
}

#endif
#endif

} // namespace OHOS


namespace OHOS {
void ProcessPlimitsTest::SetUp()
{
    RmPlimitsDir("/proc/plimits/", true);
}

void ProcessPlimitsTest::TearDown()
{
    RmPlimitsDir("/proc/plimits/", true);
}

int ProcessPlimitsTest::RmPlimitsDir(const std::string &path, bool isRoot)
{
    int ret = 0;
    DIR *pDir;
    struct dirent *pDirInfo;

    if (IsDir(path)) {
        if ((pDir = opendir(path.c_str())) == nullptr) {
            return -1;
        }
        while ((pDirInfo = readdir(pDir)) != nullptr) {
            const std::string fileName = path + "/" + pDirInfo->d_name;
            if (IsFile(fileName) || IsSpecialDir(fileName)) {
                continue;
            }
            (void)RmPlimitsDir(fileName, false);
        }
        (void)closedir(pDir);
        if (!isRoot) {
            (void)RmdirControlFile(path);
            ret = rmdir(path.c_str());
        }
    }
    return ret;
}

bool ProcessPlimitsTest::IsFile(const std::string &file)
{
    struct stat statbuf;
    return (lstat(file.c_str(), &statbuf) == 0) && S_ISREG(statbuf.st_mode);
}

bool ProcessPlimitsTest::IsDir(const std::string &path)
{
    struct stat statbuf;
    return (lstat(path.c_str(), &statbuf) == 0) && S_ISDIR(statbuf.st_mode);
}

bool ProcessPlimitsTest::IsSpecialDir(const std::string &path)
{
    return strcmp(path.c_str(), ".") == 0 || strcmp(path.c_str(), "..") == 0;
}
} // namespace OHOS

int ReadFile(const char *filepath, char *buf)
{
    FILE *fpid = nullptr;
    fpid = fopen(filepath, "r");
    ICUNIT_ASSERT_NOT_EQUAL(fpid, nullptr, -1);
    size_t trd = fread(buf, 1, 512, fpid);
    (void)fclose(fpid);
    return trd;
}

int WriteFile(const char *filepath, const char *buf)
{
    int fd = open(filepath, O_WRONLY);
    ICUNIT_ASSERT_NOT_EQUAL(fd, -1, -1);
    size_t twd = write(fd, buf, (strlen(buf)+1));
    (void)close(fd);
    return twd;
}

int RmdirControlFile(std::string path)
{
    int ret;
    std::string memControlFile = "memory";
    std::string schedControlFile = "sched";
    std::string pidsControlFile = "pids";
	std::string ipcControlFile = "ipc";
    std::string devicesControlFile = "devices";

    std::string deletePath = path + "/plimits.limiter_delete";
    ret = WriteFile(deletePath.c_str(), memControlFile.c_str());
    ret = WriteFile(deletePath.c_str(), schedControlFile.c_str());
    ret = WriteFile(deletePath.c_str(), pidsControlFile.c_str());
	ret = WriteFile(deletePath.c_str(), ipcControlFile.c_str());
    ret = WriteFile(deletePath.c_str(), devicesControlFile.c_str());
    return 0;
}

int GetLine(char *buf, int count, int maxLen, char **array)
{
    char *head = buf;
    char *tail = buf;
    char index = 0;
    if ((buf == NULL) || (strlen(buf) == 0)) {
        return 0;
    }
    while (*tail != '\0') {
        if (*tail == '\n') {
            if (index < count) {
                array[index] = head;
                index++;
                *tail = '\0';
                if (strlen(head) > maxLen) {
                    return index + 1;
                }
                tail++;
                head = tail;
            } else {
                return index + 1;
            }
        }
        tail++;
    }
    return (index + 1);
}

int RmdirTest(std::string path)
{
    int ret;
    RmdirControlFile(path);
    ret = rmdir(path.c_str());
    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
    return 0;
}

int WaitForCpupStable(int expectedCpupPercent)
{
    int sleepTime;
    if (expectedCpupPercent >= QUOTA_PERCENT_100) {
        sleepTime = WAIT_CPUP_STABLE_FOR_100;
    } else {
        sleepTime = WAIT_CPUP_STABLE;
    }
    return sleep(sleepTime);
}

static int SampleRound(void)
{
    return STATISTIC_TIMES;
}

static vector<string> GetProcessInfo(pid_t pid) {
    vector<string> contentArr;
    char buf[TEST_BUFFER_SIZE + 1] = {0};
    string strpid = to_string(pid);

    ifstream infile;
    infile.open("/proc/process");
    while (!infile.eof()) {
        infile.getline(buf, TEST_BUFFER_SIZE);
        regex e("^\\s+"+strpid);
        int matchResult = regex_search(buf, e);
        if (matchResult == 1) {
            istringstream str(buf);
            string out;
            while(str >> out) {
                contentArr.push_back(out);
            }
            break;
        }
        memset(buf, 0, TEST_BUFFER_SIZE);
    }
    infile.close();
    memset(buf, 0, TEST_BUFFER_SIZE);

    return contentArr;
}


static void SigQuit(int s)
{
    exit(0);
}

static int ChildRunCpup()
{
    int idx;
    int ret = 0;
    int i = 0;
    struct sigaction act;
    act.sa_handler = SigQuit;
    sigaction(SIGUSR1, &act, NULL);
    while (1) {
        for (i = 0; i < CHILD_LOOP_TIMES; i++) {
            ret = ret - i;
            for (idx = 0; idx < CHILD_LOOP_TIMES; idx++) {
                ret = ret | idx;
            }
        }
    }
    return 0;
}

int ForkChilds(int num, int *pidArray)
{
    pid_t childPid;
    pid_t pidArrayLocal[PROCESS_LIMIT_AMOUNT];

    for (int idx = 0; idx < num; idx++) {
        childPid = fork();
        if (childPid == 0) {
            ChildRunCpup();
        } else {
            pidArrayLocal[idx] = childPid;
            *pidArray = childPid;
            pidArray++;
        }
    }
    return 0;
}

int AddPidIntoSchedLimiters(int num, int *pidArray, const char *procspath)
{
    for (int idx = 0; idx < num; idx++) {
        string strpid = to_string(pidArray[idx]);
        WriteFile(procspath,strpid.c_str());
    }
    return 0;
}

static double GetCpup(pid_t pid) {
    auto content = GetProcessInfo(pid);
    double cpup10s = atof(content[CPUP10S_INDEX].c_str());
    return cpup10s;
}

static int CollectCpupData(int childAmount, int sampleSeconds, int *pidArray, vector<vector<double>> &cpupValuesArray)
{
    double cpup10s;
    for (int i = 0; i < sampleSeconds; i++) {
        for (int j = 0; j < childAmount;j++) {
            cpup10s = GetCpup(pidArray[j]);
            cpupValuesArray[j].push_back(cpup10s);
        }
        sleep(1);
    }
    return 0;
}

static int CalcAverageCpup(int num, vector<vector<double>> &cpupValuesArray, double *cpupAverageArray)
{
    double cpup10sAverage;
    for (int idx = 0; idx < num; idx++) {
        cpup10sAverage = std::accumulate(cpupValuesArray[idx].begin(), cpupValuesArray[idx].end(), 0.0) / cpupValuesArray[idx].size();
        cpupAverageArray[idx] = cpup10sAverage;
    }
    return 0;
}

int CreatePlimitGroup(const char* groupName, char *childPidFiles, unsigned long long periodUs, unsigned long long quotaUs)
{
    int ret;
    mode_t mode = 0777;
    char dirpath[TEST_BUFFER_SIZE];
    char procspath[TEST_BUFFER_SIZE];
    char periodpath[TEST_BUFFER_SIZE];
    char quotapath[TEST_BUFFER_SIZE];
    char periodValue[TEST_BUFFER_SIZE];
    char quotaValue[TEST_BUFFER_SIZE];

    sprintf(dirpath, "/proc/plimits/%s", groupName);
    sprintf(procspath, "%s/plimits.procs", dirpath);
    sprintf(periodpath, "%s/sched.period", dirpath);
    sprintf(quotapath, "%s/sched.quota", dirpath);

    ret = access(dirpath, 0);
    ICUNIT_ASSERT_EQUAL(ret, -1, ret);
    ret = mkdir(dirpath, mode);
    ICUNIT_ASSERT_EQUAL(ret, 0, ret);

    sprintf(periodValue, "%llu", periodUs);
    sprintf(quotaValue, "%llu", quotaUs);
    WriteFile(periodpath, periodValue);
    WriteFile(quotapath, quotaValue);
    sprintf(childPidFiles, "%s", procspath);
    return 0;
}

int CreatePlimitGroupWithoutLimit(const char* groupName, char *childPidFiles)
{
    int ret;
    mode_t mode = 0777;
    char dirpath[TEST_BUFFER_SIZE];
    char procspath[TEST_BUFFER_SIZE];

    sprintf(dirpath, "/proc/plimits/%s", groupName);
    sprintf(procspath, "%s/plimits.procs", dirpath);

    ret = access(dirpath, 0);
    ICUNIT_ASSERT_EQUAL(ret, -1, ret);
    ret = mkdir(dirpath, mode);
    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
    sprintf(childPidFiles, "%s", procspath);
    return 0;
}

int TerminateChildProcess(int *childPidArray, int childAmount, int sig)
{
    int idx;
    for (idx = 0; idx < childAmount; idx++) {
        kill(childPidArray[idx], SIGUSR1);

        int status;
        waitpid(childPidArray[idx], &status, 0);
    }

    signal(SIGUSR1, SIG_DFL);
    return 0;
}

double CalcCpupUsage(int childAmount, int *childPidArray, int expectedCpupPercent)
{
    int idx;
    int sampleSeconds = SampleRound();
    vector<vector<double>> cpupValuesArray(PROCESS_LIMIT_AMOUNT);
    CollectCpupData(childAmount, sampleSeconds, &childPidArray[0], cpupValuesArray);

    double actualCpup10sArray[PROCESS_LIMIT_AMOUNT];
    CalcAverageCpup(childAmount, cpupValuesArray, &actualCpup10sArray[0]);

    double sumAllChildsCpup = 0;
    for (idx = 0; idx < childAmount; idx++) {
        sumAllChildsCpup += actualCpup10sArray[idx];
    }
    return sumAllChildsCpup;
}

double CheckCpupUsage(double sumAllChildsCpup, int expectedCpupPercent)
{
    double errorRate = fabs(sumAllChildsCpup / expectedCpupPercent - 1.0);
    return errorRate;
}

int checkCpupUsageGreaterThan(double sumAllChildsCpup, int expectedCpupPercent)
{
    if (sumAllChildsCpup > expectedCpupPercent) {
        return 0;
    } else {
        return -1;
    }
}

double TestCpupInPlimit(int childAmount, const char* groupName,
            unsigned long long periodUs, unsigned long long quotaUs, int expectedCpupPercent)
{
    pid_t childPidArray[PROCESS_LIMIT_AMOUNT];
    char procspath[TEST_BUFFER_SIZE];
    double sumAllChildsCpup = 0;

    ForkChilds(childAmount, &childPidArray[0]);
    CreatePlimitGroup(groupName, procspath, periodUs, quotaUs);
    AddPidIntoSchedLimiters(childAmount, &childPidArray[0], procspath);
    WaitForCpupStable(expectedCpupPercent);
    sumAllChildsCpup = CalcCpupUsage(childAmount, &childPidArray[0], 0);
    double errorRate = CheckCpupUsage(sumAllChildsCpup, expectedCpupPercent);
    TerminateChildProcess(&childPidArray[0], childAmount, SIGUSR1);
    return errorRate;
}

double TestCpupWithoutLimit(int childAmount, const char* groupName, int expectedCpupPercent)
{
    pid_t childPidArray[PROCESS_LIMIT_AMOUNT];
    char procspath[TEST_BUFFER_SIZE];
    double sumAllChildsCpup = 0;

    ForkChilds(childAmount, &childPidArray[0]);
    CreatePlimitGroupWithoutLimit(groupName, procspath);
    AddPidIntoSchedLimiters(childAmount, &childPidArray[0], procspath);

    WaitForCpupStable(expectedCpupPercent);
    sumAllChildsCpup = CalcCpupUsage(childAmount, &childPidArray[0], 0);
    double errorRate = CheckCpupUsage(sumAllChildsCpup, expectedCpupPercent);
    TerminateChildProcess(&childPidArray[0], childAmount, SIGUSR1);
    return errorRate;
}

